package com.example.run_game;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.AbstractChart;
import org.achartengine.chart.BarChart;
import org.achartengine.chart.BarChart.Type;
import org.achartengine.chart.BubbleChart;
import org.achartengine.chart.ClickableArea;
import org.achartengine.chart.CubicLineChart;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.CategorySeries;
import org.achartengine.model.MultipleCategorySeries;
import org.achartengine.model.RangeCategorySeries;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.model.XYValueSeries;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.location.Location;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class GraphDisplayFragment extends Fragment
{
	private static ArrayList<Location> route;

	public GraphDisplayFragment()
	{
	}

	public static Fragment newInstance(ArrayList<Location> mMarkers)
	{
        Bundle args = new Bundle();
        args.putParcelableArrayList("route", mMarkers);
        
		GraphDisplayFragment f = new GraphDisplayFragment();
        f.setArguments(args);

		return f;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState)
	{

		System.out.println(getArguments());
		ArrayList<Parcelable> l = getArguments().getParcelableArrayList("route");
		ArrayList<Location> route = new ArrayList<Location>(l.size());

		for (Parcelable parcelable : l)
		{
			Location loc = (Location)parcelable;
			System.out.println(loc);
			route.add(loc);
		}
		DistanceSpeedElevationGraph chart = new DistanceSpeedElevationGraph(route);
		View view = chart.getView();
		return view;
	}

	public class DistanceSpeedElevationGraph
	{
		private ArrayList<Location> route;

		public DistanceSpeedElevationGraph (ArrayList<Location> mRoute)
		{
			route = Utils.addSpeedsToRoute(mRoute);
		}
		
		public GraphicalView getView()
		{
			Log.d("graph",DistanceSpeedElevationGraph.this.route.toString());
			ArrayList<Location> rt = DistanceSpeedElevationGraph.this.route;
			double maxElev = Double.NEGATIVE_INFINITY;
			double minElev = Double.POSITIVE_INFINITY;
			double maxVelo = Double.NEGATIVE_INFINITY;
			double minVelo = Double.POSITIVE_INFINITY;
			
			for (Location l : rt)
			{
				if (l.getAltitude() > maxElev)
					maxElev = l.getAltitude();
				if (l.getAltitude() < minElev)
					minElev = l.getAltitude();
				if (l.getSpeed() > maxVelo)
					maxVelo = l.getSpeed();
				if (l.getSpeed() < minVelo)
					minVelo = l.getSpeed();
			}
			System.out.println("Max elev = " + maxElev +
								"\nMin elev = " + minElev +
								"\nMax velo = " + maxVelo +
								"\nMin velo = " + minVelo);
			
			Long startTime 	= rt.get(0).getTime();
			Long endTime 	= rt.get(rt.size()-1).getTime();
			Long diff = endTime-startTime;
			int minutes = (int) Math.ceil(1.0*diff / (1000*60));
		
			double[] veloValues = new double[minutes+1];
			double[] xAxis = new double[minutes+1];
			double[] elevValues = new double[minutes+1];
			Log.d("speed","total minutes: "+minutes);
			Location loc = rt.get(0);
			long starttime = loc.getTime();
			for (int i = 0; i < minutes; i++)
			{
				long targettime = starttime + (i*1000*60);
				long overshoottime = starttime + ((i+1)*1000*60);
				Location targetLocation = loc;
				for (Location l : rt)
				{
					if (l.getTime() > overshoottime)
						break;
					if (l.getTime() < targettime)
						continue;
					else
					{
						targetLocation = l;
						break;
					}
				}
				elevValues[i] = targetLocation.getAltitude();
				veloValues[i] = targetLocation.getSpeed();
				xAxis[i] = i;
			}
			veloValues[minutes] = rt.get(rt.size()-1).getSpeed();
			elevValues[minutes] = rt.get(rt.size()-1).getAltitude();
			xAxis[minutes] = minutes;
			
			for (double v : veloValues)
				Log.d("speed","point: "+v);
			
			Log.d("speed","vLen:"+veloValues.length+"  xAxis:"+xAxis.length+"  elevLen:"+elevValues.length);
			
			String[] titles = new String[] { "Speed" };
		    List<double[]> x = new ArrayList<double[]>();
		    
		    for (int i = 0; i < titles.length; i++) {
		    	x.add(xAxis);
		    }
		    List<double[]> values = new ArrayList<double[]>();
		    values.add(veloValues);
		    int[] colors = new int[] { Color.MAGENTA, Color.YELLOW };
		    PointStyle[] styles = new PointStyle[] { PointStyle.POINT, PointStyle.POINT };
		    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(2);
		    setRenderer(renderer, colors, styles);
		    int length = renderer.getSeriesRendererCount();
		    for (int i = 0; i < length; i++) {
		      XYSeriesRenderer r = (XYSeriesRenderer) renderer.getSeriesRendererAt(i);
		      r.setLineWidth(3f);
		    }
		    setChartSettings(renderer, "Elevation vs. Speed", "Minutes", "kph", 0, minutes, 0, maxVelo,
		        Color.LTGRAY, Color.LTGRAY);
		    renderer.setXLabels(12);
		    renderer.setYLabels(10);
		    renderer.setShowGrid(true);
		    renderer.setXLabelsAlign(Align.RIGHT);
		    renderer.setYLabelsAlign(Align.RIGHT);
		    renderer.setZoomButtonsVisible(true);
		    renderer.setPanLimits(new double[] { -10, 20, -10, 40 });
		    renderer.setZoomLimits(new double[] { -10, 20, -10, 40 });
		    renderer.setZoomRate(1.05f);
		    renderer.setLabelsColor(Color.WHITE);
		    renderer.setXLabelsColor(Color.GREEN);
		    renderer.setYLabelsColor(0, colors[0]);
		    renderer.setYLabelsColor(1, colors[1]);

		    renderer.setYTitle("Feet above sea level", 1);
		    renderer.setYAxisAlign(Align.RIGHT, 1);
		    renderer.setYLabelsAlign(Align.LEFT, 1);

		    XYMultipleSeriesDataset dataset = buildDataset(titles, x, values);
		    values.clear();
		    values.add(elevValues);
		    addXYSeries(dataset, new String[] { "Elevation" }, x, values, 1);
		    GraphicalView view = ChartFactory.getLineChartView(getActivity(), dataset, renderer);
		    return view;
		}
		
		  protected XYMultipleSeriesDataset buildDataset(String[] titles, List<double[]> xValues,
			      List<double[]> yValues) {
			    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
			    addXYSeries(dataset, titles, xValues, yValues, 0);
			    return dataset;
			  }

			  public void addXYSeries(XYMultipleSeriesDataset dataset, String[] titles, List<double[]> xValues,
			      List<double[]> yValues, int scale) {
			    int length = titles.length;
			    for (int i = 0; i < length; i++) {
			      XYSeries series = new XYSeries(titles[i], scale);
			      double[] xV = xValues.get(i);
			      double[] yV = yValues.get(i);
			      int seriesLength = xV.length;
			      for (int k = 0; k < seriesLength; k++) {
			        series.add(xV[k], yV[k]);
			      }
			      dataset.addSeries(series);
			    }
			  }

			  /**
			   * Builds an XY multiple series renderer.
			   * 
			   * @param colors the series rendering colors
			   * @param styles the series point styles
			   * @return the XY multiple series renderers
			   */
			  protected XYMultipleSeriesRenderer buildRenderer(int[] colors, PointStyle[] styles) {
			    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
			    setRenderer(renderer, colors, styles);
			    return renderer;
			  }

			  protected void setRenderer(XYMultipleSeriesRenderer renderer, int[] colors, PointStyle[] styles) {
			    renderer.setAxisTitleTextSize(16);
			    renderer.setChartTitleTextSize(20);
			    renderer.setLabelsTextSize(15);
			    renderer.setLegendTextSize(15);
			    renderer.setPointSize(5f);
			    renderer.setMargins(new int[] { 20, 30, 15, 20 });
			    int length = colors.length;
			    for (int i = 0; i < length; i++) {
			      XYSeriesRenderer r = new XYSeriesRenderer();
			      r.setColor(colors[i]);
			      r.setPointStyle(styles[i]);
			      renderer.addSeriesRenderer(r);
			    }
			  }

			  /**
			   * Sets a few of the series renderer settings.
			   * 
			   * @param renderer the renderer to set the properties to
			   * @param title the chart title
			   * @param xTitle the title for the X axis
			   * @param yTitle the title for the Y axis
			   * @param xMin the minimum value on the X axis
			   * @param xMax the maximum value on the X axis
			   * @param yMin the minimum value on the Y axis
			   * @param yMax the maximum value on the Y axis
			   * @param axesColor the axes color
			   * @param labelsColor the labels color
			   */
			  protected void setChartSettings(XYMultipleSeriesRenderer renderer, String title, String xTitle,
			      String yTitle, double xMin, double xMax, double yMin, double yMax, int axesColor,
			      int labelsColor) {
			    renderer.setChartTitle(title);
			    renderer.setXTitle(xTitle);
			    renderer.setYTitle(yTitle);
			    renderer.setXAxisMin(xMin);
			    renderer.setXAxisMax(xMax);
			    renderer.setYAxisMin(yMin);
			    renderer.setYAxisMax(yMax);
			    renderer.setAxesColor(axesColor);
			    renderer.setLabelsColor(labelsColor);
			  }

			  /**
			   * Builds an XY multiple time dataset using the provided values.
			   * 
			   * @param titles the series titles
			   * @param xValues the values for the X axis
			   * @param yValues the values for the Y axis
			   * @return the XY multiple time dataset
			   */
			  protected XYMultipleSeriesDataset buildDateDataset(String[] titles, List<Date[]> xValues,
			      List<double[]> yValues) {
			    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
			    int length = titles.length;
			    for (int i = 0; i < length; i++) {
			      TimeSeries series = new TimeSeries(titles[i]);
			      Date[] xV = xValues.get(i);
			      double[] yV = yValues.get(i);
			      int seriesLength = xV.length;
			      for (int k = 0; k < seriesLength; k++) {
			        series.add(xV[k], yV[k]);
			      }
			      dataset.addSeries(series);
			    }
			    return dataset;
			  }

			  /**
			   * Builds a category series using the provided values.
			   * 
			   * @param titles the series titles
			   * @param values the values
			   * @return the category series
			   */
			  protected CategorySeries buildCategoryDataset(String title, double[] values) {
			    CategorySeries series = new CategorySeries(title);
			    int k = 0;
			    for (double value : values) {
			      series.add("Project " + ++k, value);
			    }

			    return series;
			  }

			  /**
			   * Builds a multiple category series using the provided values.
			   * 
			   * @param titles the series titles
			   * @param values the values
			   * @return the category series
			   */
			  protected MultipleCategorySeries buildMultipleCategoryDataset(String title,
			      List<String[]> titles, List<double[]> values) {
			    MultipleCategorySeries series = new MultipleCategorySeries(title);
			    int k = 0;
			    for (double[] value : values) {
			      series.add(2007 + k + "", titles.get(k), value);
			      k++;
			    }
			    return series;
			  }

			  /**
			   * Builds a category renderer to use the provided colors.
			   * 
			   * @param colors the colors
			   * @return the category renderer
			   */
			  protected DefaultRenderer buildCategoryRenderer(int[] colors) {
			    DefaultRenderer renderer = new DefaultRenderer();
			    renderer.setLabelsTextSize(15);
			    renderer.setLegendTextSize(15);
			    renderer.setMargins(new int[] { 20, 30, 15, 0 });
			    for (int color : colors) {
			      SimpleSeriesRenderer r = new SimpleSeriesRenderer();
			      r.setColor(color);
			      renderer.addSeriesRenderer(r);
			    }
			    return renderer;
			  }

			  /**
			   * Builds a bar multiple series dataset using the provided values.
			   * 
			   * @param titles the series titles
			   * @param values the values
			   * @return the XY multiple bar dataset
			   */
			  protected XYMultipleSeriesDataset buildBarDataset(String[] titles, List<double[]> values) {
			    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
			    int length = titles.length;
			    for (int i = 0; i < length; i++) {
			      CategorySeries series = new CategorySeries(titles[i]);
			      double[] v = values.get(i);
			      int seriesLength = v.length;
			      for (int k = 0; k < seriesLength; k++) {
			        series.add(v[k]);
			      }
			      dataset.addSeries(series.toXYSeries());
			    }
			    return dataset;
			  }

			  /**
			   * Builds a bar multiple series renderer to use the provided colors.
			   * 
			   * @param colors the series renderers colors
			   * @return the bar multiple series renderer
			   */
			  protected XYMultipleSeriesRenderer buildBarRenderer(int[] colors) {
			    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
			    renderer.setAxisTitleTextSize(16);
			    renderer.setChartTitleTextSize(20);
			    renderer.setLabelsTextSize(15);
			    renderer.setLegendTextSize(15);
			    int length = colors.length;
			    for (int i = 0; i < length; i++) {
			      SimpleSeriesRenderer r = new SimpleSeriesRenderer();
			      r.setColor(colors[i]);
			      renderer.addSeriesRenderer(r);
			    }
			    return renderer;
			  }
		
	}
}
	
